package org.hackystat.devcathlon.ui.page.scoreboard.halloffame;

import static org.junit.Assert.assertEquals;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.wicket.util.tester.FormTester;
import org.apache.wicket.util.tester.WicketTester;
import org.hackystat.devcathlon.configuration.ConfigurationManager;
import org.hackystat.devcathlon.engine.event.Event;
import org.hackystat.devcathlon.engine.event.EventScore;
import org.hackystat.devcathlon.engine.event.impl.CollectiveOwnership;
import org.hackystat.devcathlon.engine.match.Match;
import org.hackystat.devcathlon.engine.team.Team;
import org.hackystat.devcathlon.engine.test.DevcathlonTestHelper;
import org.hackystat.devcathlon.engine.user.User;
import org.hackystat.devcathlon.ui.DevcathlonApplication;
import org.hackystat.devcathlon.ui.page.matches.MatchesPage;
import org.hackystat.devcathlon.ui.page.matches.browse.BrowsePage;
import org.hackystat.devcathlon.ui.page.matches.invitations.InvitationsPage;
import org.hackystat.devcathlon.ui.page.matches.manage.MatchesManagePage;
import org.hackystat.devcathlon.ui.page.scoreboard.ScoreboardPage;
import org.hackystat.sensorbase.resource.projects.jaxb.Project;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Tests the Hall of Fame implementation.
 * 
 * @author Daniel Arakaki, Robin Raqueno
 */
public class TestHallofFamePage extends DevcathlonTestHelper {
  private String teamName1 = "TestTeam1";
  private String teamOwner1 = "TeamOwner1";
  private String matchName1 = "TestMatch1";
  private String member1a = "Member1a";
  private String member1b = "Member1b";
  private String teamName2 = "TestTeam2";
  private String teamOwner2 = "TeamOwner2";
  private String member2a = "Member2a";
  private String member2b = "Member2b";
  
  /** Wakeup interval in minutes. */
  private static int wakeupInterval = 1440;
  
  /** Minutes needed for points. */
  private static int devTimeMinutes = 60;
  
  /** Points awarded. */
  private static int awardPoints = 10;

  /** Percentage of files that should be worked on. */
  private static int filesPercentage = 50;
  
  /** Number of developers that should be working on the files. */
  private static int minNumDevelopers = 2;
  
  /** Minutes needed for points. */
  private static int bonusDevTimeMinutes = 60;
  
  /** Points awarded. */
  private static int bonusAwardPoints = 5;
  
  /** Percentage of files that should be worked on. */
  private static int bonusFilesPercentage = 90;

  /** Number of developers that should be working on the files. */ 
  private static int bonusMinNumDevelopers = 2;
  
  /** Sensor base host URL. */
  private String sensorBaseHost = "http://localhost:9976/sensorbase/";
  
  /** Daily project data host URL. */
  private String dailyProjectDataHost = "http://localhost:9977/dailyprojectdata/";
  
  /**
   * Sets up the DevcathlonConfiguration for use in these test cases. 
   * @throws Exception If problems occur setting up the configuration. 
   */
  @BeforeClass
  public static void setupConfiguration() throws Exception {
    // Set up the testing DevcathlonConfiguration for the event CollectiveOwnership.
    String eventName = CollectiveOwnership.eventName;
    ConfigurationManager configManager = ConfigurationManager.getInstance();
    configManager.setBaseScoreWeight(eventName, 1);
    configManager.getConfiguration(eventName);
    configManager.setWakeupInterval(eventName, wakeupInterval);
    
    configManager.addProperty(eventName, CollectiveOwnership.devTimeMinutesKey, 
                              Integer.toString(devTimeMinutes));
    configManager.addProperty(eventName, CollectiveOwnership.awardPointsKey, 
                              Integer.toString(awardPoints));
    configManager.addProperty(eventName, CollectiveOwnership.filesPercentageKey, 
                              Integer.toString(filesPercentage));
    configManager.addProperty(eventName, CollectiveOwnership.minNumDevelopersKey, 
                              Integer.toString(minNumDevelopers));
    configManager.addProperty(eventName, CollectiveOwnership.bonusDevTimeMinutesKey, 
                              Integer.toString(bonusDevTimeMinutes));
    configManager.addProperty(eventName, CollectiveOwnership.bonusAwardPointsKey, 
                              Integer.toString(bonusAwardPoints));
    configManager.addProperty(eventName, CollectiveOwnership.bonusFilesPercentageKey, 
                              Integer.toString(bonusFilesPercentage));
    configManager.addProperty(eventName, CollectiveOwnership.bonusMinNumDevelopersKey, 
                              Integer.toString(bonusMinNumDevelopers));
  }
  /**
   * Test Hall of Fame Page.
   * 
   * @throws Exception Unexpected error.
   */
  @Test
  public void testPage() throws Exception {
    // Create the teams. 
    Team team1 = makeTeam(teamName1, teamOwner1, member1a, member1b);
    Team team2 = makeTeam(teamName2, teamOwner2, member2a, member2b);
    
    Project project1 = getProject(teamOwner1, teamName1);
    Project project2 = getProject(teamOwner2, teamName2);
    
    // Now create the event instance.
    Event event = new CollectiveOwnership();
    
    // Create a simple match containing a single team, a single project, and this event.
    Match match = addTwoTeamMatch(matchName1, team1, team2, project1, project2, event);
    
    XMLGregorianCalendar devEventEndTime = Tstamp.makeTimestamp();
    XMLGregorianCalendar devEventStartTime = Tstamp.incrementMinutes(devEventEndTime,
                                                                     -1 * wakeupInterval);
    int i = 1;
    for (User user : team1.getMembers()) {
      for (; i <= 2; i++) {
        makeDevTimeData(user, project1, devEventStartTime, devTimeMinutes, "/file" + i + ".java");
        devEventStartTime = Tstamp.incrementMinutes(devEventStartTime, devTimeMinutes + 1);
      }
      makeBuildData(user, project1, Tstamp.incrementMinutes(devEventStartTime, 1), true);
      i = 2;
    }

    // Test the event with no sensor data.
    EventScore score = event.computeScore(match, team1, Tstamp.makeTimestamp());
    assertEquals("Check base 1", awardPoints, score.getBaseScore());
    assertEquals("Check bonus 1", 0, score.getBonusScore(CollectiveOwnership.bonusName));
    assertEquals("Check points 1", awardPoints, event.computePoints(score));
 
    DevcathlonApplication devcathlonApplication = new DevcathlonApplication(
                                           dailyProjectDataHost, sensorBaseHost);
    WicketTester tester = new WicketTester(devcathlonApplication);
    tester.setupRequestAndResponse();
    
    tester.startPage(devcathlonApplication.getHomePage());
    tester.assertRenderedPage(devcathlonApplication.getHomePage());
    
   
    FormTester formTester = tester.newFormTester("loginForm");
    formTester.setValue("user", "admin@hackystat.org");
    formTester.setValue("password", "admin@hackystat.org");
    formTester.submit();
    
    tester.clickLink("HallofFameLink");
    tester.assertRenderedPage(HallofFamePage.class);
    //tester.dumpPage();
    
    tester.clickLink("ScoreboardLink");
    tester.assertRenderedPage(ScoreboardPage.class);
    
    tester.clickLink("MatchesLink");
    tester.assertRenderedPage(MatchesPage.class);
    
    tester.clickLink("MatchesManageLink");
    tester.assertRenderedPage(MatchesManagePage.class);
    
    tester.clickLink("BrowseLink");
    tester.assertRenderedPage(BrowsePage.class);
    
    tester.clickLink("InvitationsLink");
    tester.assertRenderedPage(InvitationsPage.class);
    
    //tester.clickLink("CreateMatchLink");
    //tester.assertRenderedPage(CreateNewMatchPanel.class);
    
    
    //tester.debugComponentTrees();
    deleteTeam(teamName2);
    deleteTeam(teamName1);
    deleteMatch(matchName1);
  }
}
